perm filename INGLUK.MAC[IP,SYS] blob sn#680208 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-INET>INGLUK.MAC.40303  12-Apr-82 21:02:57, Edit by CLYNN
; Written for Multinet/Internet, GWYLUK just returns address in T1

	SEARCH	PROLOG
	TTITLE	INGLUK
	SUBTTL	Gateway Table Accessing and Updating Routines
	SWAPCD

	SEARCH	INPAR			; Get Internet definitions
IFN	MNET,<
	SEARCH	MNTPAR			; Get Multinet definitions
>

COMMENT	!
	Dan Tappan 2/82

	This module contains routines for maintaining and accessing
	net<->gateway tables.

	It exports the following routines:

* GWYLUK ..  3 .. Look up a gateway address for a given destination.
* INTUP ...  5 .. Report an interface as up.
* INTDWN ..  6 .. Report an interface as down.
* GWYDWN ..  7 .. Report a gateway as down.
* NETHSI ..  8 .. Initialize the network hash table.
* NETHSH ..  9 .. Hash a net number into the lookup table.

	It imports the following:

  FNDGWY  INCMP   Find a gateway to get to a given network.
	!

;;; GWYLUK -- Look up a gateway address for a given destination.
;;; Accepts	T1/	32 bit destination address
;;; Returns	T1/	0 if no path to the destination, or
;;;			Interface# & Address of a gateway/host on a
;;;			connected network that can gateway to that
;;;			destination (may be the same destination)
;;;		T2/	Garbage
;;;		T3/	If system runs Multinet, garbage; otherwise
;;;			the interface index to use (-1,,index).
;;;		P1/	If system runs multinet the address of the
;;;			NCT for an interface to use ((0 or -1),,index)
;;;			0 if no path


GWYLUK::ACVAR	<NET>
	NETNUM T2,T1			; Get the network number
	MOVEM T2,NET			; Save number
	CALL NETHSH ;(T2 to T2, killing 3,4); Hash the network into tables
	 JRST LUKNIT			; not in the tables
IFE MNET,<
	SKIPGE T3,NETGWY(T2)		; Gateway address?
	 RET		; -1,,index	; No, return with interface
	JUMPE T3,LUKNIT			; Deleted entry
; Found gateway
	MOVE T1,T3			; get host address
>
IFN MNET,<
	SKIPGE P1,NETGWY(T2)		; Gateway?
	 RET		; -1,,.NCTi	; No, return with interface
	JUMPE P1,LUKNIT			; Deleted entry
; Found gateway
	MOVE T1,P1			; get address
>
GWYL5:	LOAD T3,INTNUM,+T1		; get interface index
IFN	MNET,<
	MOVE P1,NCTVT(T3)		; get NCT address
>
	TLN T1,740000			; Just 32-bit address
	RET				; and return with it

;;; Here if there is no entry in the network tables
;;; for that net.
;;; T1/ destination,  T2/ net hash index of empty slot in NETGWY



LUKNIT:	PUSH P,T2			; Save hash table index
	CALL FNDGWY			; Find a gateway
	JUMPE T1,[POP P,T2		; Restore hash address
		  RET]			; Return unsucessfully
	CALL FNDNCT			; Find interface for this one
	 INBUG	(HLT,<FNDGWY returned unconnected gateway>,GWYFNB)
IFN	MNET,<
	LOAD T2,NTNUM,(P1)		; Get interface index
>
	STOR T2,INTNUM,+T1		; save interface index
	POP P,T2			; restore hash address
	MOVEM T1,NETGWY(T2)		; place gateway in tables
	JRST GWYL5			; and join above

;	ENDAV.


;;; INTUP -- Signal that an interface has come up
;;; Called	T1/	Interface index (if not multinet)
;;;		P1/	NCT address (If multinet)


INTUP::
IFN	MNET,<
	MOVE T2,NTNET(P1)		; get network number
>
IFE	MNET,<
	TXO T1,1B0			; flag it
	PUSH P,T1			; save entry
	MOVE T1,NLHOST(T1)		; get host number
	NETNUM T2,T1			; And the net number from it
>
	CALL NETHSH			; hash the entry
	 NOP				; ignore failure
IFN	MNET,<
	HRROM P1,NETGWY(T2)		; save NCT
>
IFE	MNET,<
	POP P,NETGWY(T2)		; drop in index
>
	RET				; and return

;;; INTDWN -- Signal that an interface has gone down.
;;; Called	P1/	NCT for the interface (if multinet)
;;;		T1/	Interface index (if not)


INTDWN::SAVET
	STKVAR	<INDEX>			; interface index
IFE	MNET,<
	MOVEM T1,INDEX		; save index
	MOVE T1,NLHOST(T1)		; get address
	NETNUM T2,T1			; Get the net number
>
IFN	MNET,<
	MOVE T1,NTLADR(P1)		; Get our address
	MOVE T2,NTNET(P1)		; and it's net number
>
	CALL NETHSH			; Hash it
	 INBUG (HLT,<INTDWN -- Impossible failure of NETHSH>,INTDHF)
	SETZM NETGWY(T2)		; don't use this interface
IFN	MNET,<
	LOAD T2,NTNUM,(P1)		; Get the internal index
	MOVEM T2,INDEX			; Save it
>
	MOVSI T2,-NETHSZ		; size of hash table

;;; INDEX has interface index
;;; T2 has index into hash table

INTDWL:	SKIPG T1,NETGWY(T2)		; Anything in this slot?
	 JRST INTDL2			; no, onward
	LOAD T4,INTNUM,+T1		; get index of this number
	CAME T4,INDEX			; Same interface?
	 JRST INTDL2			; mark it down
	SETZM NETGWY(T2)		; erase that entry
INTDL2:	AOBJN T2,INTDWL			; loop through the table
	RET				; and return

;;; GWYDWN -- Signal that a gateway has crashed.
;;; Called	T1/	Address of gateway
;;; Returns	T2,T3 clobbered
;;; 		all paths using this gateway erased.


GWYDWN::
	MOVSI T2,-NETHSZ		; Size of the hash tables
GWYDWL:	SKIPG T3,NETGWY(T2)		; get address
	 JRST GWYDW2			; None there
	TXZ T3,-1B3			; Clear the index field
	CAMN T1,T3			; this gateway a path to there?
	 SETZM NETGWY(T2)		; Yes, flush it
GWYDW2:	AOBJN T2,GWYDWL			; Loop through the table
	RET				; and return


;;; NETHSI -- Initialize the network hash table
;;; Called at system startup, whenever the hash table
;;; overflows, and at random times to flush unused
;;; table entries


NETHSI::
IFN MNET,<SAVP1>
	NOSKED				; Take over the machine
	SETZM NETHTB			; Clear
	MOVE T1,[XWD NETHTB,NETHTB+1]
	BLT T1,NETHTB+NETHSZ		; The entire table
	SETZM NETGWY			; And
	MOVE T1,[XWD NETGWY,NETGWY+1]
	BLT T1,NETGWY+NETHSZ		; the parallel table
IFN	MNET,<
	XMOVEI P1,NCTVT			; Point to NCT vector table
NETHI0:	LOAD P1,NTLNK,(P1)		; get next in chain
	JUMPE P1,NETHIX			; done
	MOVE T2,NTNET(P1)		; get the net number
	CALL NETHSH			; Hash it into tables
	 NOP				; Ignore return
	SKIPE NTORDY(P1)		; If this network is usable
	 HRROM P1,NETGWY(T2)		; Set it as the path to this net
	JRST NETHI0			; And loop through all interfaces
>
IFE	MNET,<
	MOVSI T4,-%NETS			; Number of interfaces
NETHI0:	MOVE T1,NLHOST(T4)		; Get an address
	NETNUM T2,T1			; extract the network number
	CALL NETHSH			; hash it into the tables
	 NOP				; ignore return
	HRROM T4,NETGWY(T2)		; Save the address
	AOBJN T4,NETHI0			; and loop through all
>
NETHIX:	OKSKED				; Allow use of the machine
	RET				; return when done

;;; NETHSH -- Look up a netwrk number in the hash tables
;;; Called
;;;	T2/	network number
;;; Returns
;;;	T2/	Slot in the table for that network 
;;;	Clobbers T3, T4
;;;	+1 if no entry currently there
;;;	(the slot is reserved in that case)
;;;	+2 if that network already has a slot in the tables


NETHSH::ACVAR	<NET>			; net number
	MOVE NET,T2			; Save it here
	IDIVI T2,NETHSZ			; Make the initial probe
	EXCH T2,T3			; ...
	NOSKED				; protect the table

;;; The following is an optimization for the 
;;; (hopefully common) case where there is no collision
;;; and/or the entry is already in the table.

	CAMN NET,NETHTB(T2)		; Same entry?
	 JRST NETHSS			; Success, go use it
	SKIPN NETHTB(T2)		; Empty?
	 JRST NETHSF			; First probe failed
	IDIVI T3,NETHSZ			; divide again to get the delta
	SKIPN T4			; If there is none
	 MOVEI T4,1			; use 1
	MOVEI T3,NETHSZ-1		; size of the tables

;;; At this point T2 holds the current probe, T4 holds the delta,
;;; T3 holds the number of attempts before deciding the table is full.
;;; The current table slot is not this net.

NETHSL:	ADDI T2,(T4)			; Add in the delta
	CAIL T2,NETHSZ			; Overflow?
	 SUBI T2,NETHSZ			; back up
	CAMN NET,NETHTB(T2)		; Same net?
	 JRST NETHSS			; found it
	SKIPN NETHTB(T2)		; Slot in use?
	 JRST NETHSF			; Empty, use it
	SOJG T3,NETHSL			; loop through the table

;;; Here if the table is full.
;;; we reinitialize the table, since we assume that the
;;; table is large enough to hold all networks with active connections.

	CALL NETHSI			; re-init the table
	MOVE T2,NET			; Get the network number back
	CALL NETHSH			; hash it
	 INBUG (HLT,<Impossible failure of NETHSH>,NTHSHF)

;;; Here if an entry is found

NETHSS:	OKSKED				; Allow scheduling again
	RETSKP				; return success

;;; Here if there is no entry for this net 

NETHSF:	MOVEM NET,NETHTB(T2)		; Reserve a table slot
	OKSKED
	RET				; return failure

;	ENDAV.



IFE MNET,<

;;; Dummy routines used if system is not running the Multinet software

;;; FNDNCT -- Find the interface for a given host address
;;; Called T1/	32 bit address
;;; Returns +2 if host has an interface on that machine, with T3
;;; holding the index
;;; Dummy routine always assumes success.

FNDNCT::
	SETZ T3,			; Assume 0
	RETSKP				; return good

> ; End of dummy routines

	TNXEND
	END

; Local Modes:
; Mode:Macro
; Comment C